package com.example.myblog.service.impl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.myblog.constants.UserConstants;
import com.example.myblog.dto.UserDTO;
import com.example.myblog.entity.User;
import com.example.myblog.exception.BaseException;
import com.example.myblog.mapper.UserMapper;
import com.example.myblog.result.BaseCodeEnum;
import com.example.myblog.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.myblog.utils.MD5;
import com.example.myblog.utils.RedisUtils;
import com.example.myblog.utils.UserThreadLocal;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import static com.example.myblog.constants.RedisConstants.*;
import static com.example.myblog.constants.UserConstants.*;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author 叶兴
 * @since 2022-09-29
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    private UserMapper userMapper;

    private RedisUtils redisUtils;

    @Autowired
    public void setRedisUtils(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }

    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertUser(String username, String password) throws BaseException {
        // 1. 判断该用户是否已经存在
        QueryWrapper<User> userQueryWrapper = Wrappers.query();
        userQueryWrapper.eq("user_name",username);
        if (userMapper.selectOne(userQueryWrapper) != null) {
            // 2. 存在则不可加入，返回0
            throw new BaseException(BaseCodeEnum.USER_EXISTS);
        } else {
            // 3. 不存在则可加入，返回1
            User user = new User();
            user.setUserName(username);
            String passMD5 = MD5.generate(password);
            user.setUserPassword(passMD5);
            user.setUserCreated(LocalDate.now());
            user.setUserHead(USER_HEAD);
            userMapper.insert(user);
            return 1;
        }
    }

    @Override
    public String selectUser(String username, String password) throws BaseException {
        UserDTO userDTO = new UserDTO();
        // 1. 判断是否存在此用户
        QueryWrapper<User> userQueryWrapper = Wrappers.query();
        userQueryWrapper.eq("user_name",username);
        User user = userMapper.selectOne(userQueryWrapper);
        // 不存在返回null
        if (user == null) {
            throw new BaseException(BaseCodeEnum.USER_NOT_EXISTS);
        }
        // 2. 若存在则判断账户密码是否对应
        boolean verify = MD5.verify(password, user.getUserPassword());
        if (!verify) {
            throw new BaseException(BaseCodeEnum.PASSWORD_ERROR);
        }
        // 3. 若对应则放行
        BeanUtils.copyProperties(user,userDTO);
        // 4. 设置登录令牌
        String token = UUID.randomUUID().toString(true);
        // 5. 拼接存入 Redis 的key
        String key = USER_LOGIN_KEY + token;
        // 6. 存入 Redis
        redisUtils.loadByHash(key,userDTO,USER_LOGIN_TTL, TimeUnit.MINUTES);
        UserThreadLocal.setUserDto(userDTO);
        return token;
    }

    @Override
    public int logout(String username) throws BaseException {
        // 1. 根据 username 清除 redis 中的 cookie

        // 2. 清除成功返回 1

        // 3. 否则抛出异常

        return 1;
    }

    @Override
    public Map<String, String> updateAvatar(MultipartFile avatar) {
        return null;
    }

    @Override
    public UserDTO getUserInfo(String username) throws BaseException {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name",username);
        User user = getOne(wrapper);
        if (user == null) {
            throw new BaseException(BaseCodeEnum.USER_NOT_EXISTS);
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(user,userDTO);
        return userDTO;
    }

    @Override
    public boolean ifUserExists(String username) throws BaseException {
        QueryWrapper<User> userQueryWrapper = new QueryWrapper<>();
        userQueryWrapper.eq("user_name",username);
        User user = userMapper.selectOne(userQueryWrapper);
        if (user == null) {
            throw new BaseException(BaseCodeEnum.USER_NOT_EXISTS);
        }

        return true;
    }


}
